package com.hspedu.qqserver.service;

import com.hspedu.qqcommon.Message;
import com.hspedu.qqcommon.MessageType;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 吴宇~
 * @motto 我亦无他，唯手熟尔。
 * @edition jdk1.8
 * @reflection 0-1 喧闹任其喧闹，自由我自为之，我自风情万种，与世无争。
 * @date 2023/03/20/19:40
 */
//服务端连接客户端的线程
//该类的一个对象必须和客户端保持通信,接收端的线程
public class ServerConnectClientThread extends Thread {
    private Socket socket;//这个socket指的是每一个实例化对象都有一个socket属性，这个属性代表监听接口
    private String userID;


    public ServerConnectClientThread(Socket socket, String userID) {
        this.socket = socket;
        this.userID = userID;
    }

    public Socket getSocket() {
        return socket;
    }

    @Override
    public void run() {//这里线程处于run状态，可以发送和接收消息
        while (true) {//这个线程不停的在接收客户端发送的数据，然后做出回应，达到通信的目的
            System.out.println("用户(" + userID + ")登录,保持通信，读取数据。。");
            try {
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                Message message = (Message) ois.readObject();

                //根据message的类型做相应的处理
                if (message.getMesType().equals(MessageType.MESSAGE_GET_ONLINE_FRIEND)) {
                    /**
                     * ??sender  没设置了，的确，老师没设置
                     */
                    System.out.println(message.getSender() + "要在线用户列表");
                    //因为要返回message对象,所以构建一个message对象
                    Message message2 = new Message();
                    message2.setMesType(MessageType.MESSAGE_RET_ONLINE_FRIEND);//ret指的是return
                    message2.setContent(MangerClientThreads.getOnlineUser());//信息填入到message
                    //message的发送者是message2的接受者
                    message2.setGetter(message.getSender());
                    //返回个客户端
                    ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                    oos.writeObject(message2);
                } else if (message.getMesType().equals(MessageType.MESSAGE_CLIENT_EXIT)) {//客户端要退出
                    System.out.println(message.getSender() + "退出登录");
                    //将客户端对应的线程从集合中移除，这句话就是说从后台集合中查看不到客户端了
                    MangerClientThreads.removeServerConnectClientThread(message.getSender());
                    socket.close();
                    //socket是关闭连接，还得退出线程
                    break;   //break退出while循环，即结束run方法，即结束线程，总的来说，线程得指望循环来实现
                } else if (message.getMesType().equals(MessageType.MESSAGE_COMM_MES)) {
                    //根据message获取id再得到对应的线程.线程得到接口socket，得到输出流发送message
                    /**
                     * 假如这儿不使用getSocket的话，使用socket是否行呢，完了试一下！不行，刚试了，确实不行，！！
                     * 但是想不通
                     */
                    /**
                     *                             ServerConnectClientThread serverConnectClientThread = MangerClientThreads.getServerConnectClientThread(message.getGetter());
                     *                             Socket socket = serverConnectClientThread.getSocket();
                     *                             OutputStream outputStream = socket.getOutputStream();
                     *                             ObjectOutputStream oot = new ObjectOutputStream(outputStream);
                     *                             oot.writeObject(message);//如果用户不在线的话就做成离线的消息了,怎么做呢，就和微信一样，只要自己有网，发了就一定能接收
                     *                              * 如果用户在线，保存到数据库，离线留言
                     */
                    String[] s = MangerClientThreads.getOnlineUser().split(" ");
                    for (int i = 0; i < s.length; i++) {//拿每一个在线用户和这个信息的接收者对比，如果在线的haul，就发送这个消息，如果不在线的话，就保存这个消息
                        if (message.getGetter().equals(s[i])) {//如果在线的话就发送信息
                            ServerConnectClientThread serverConnectClientThread = MangerClientThreads.getServerConnectClientThread(message.getGetter());
                            Socket socket = serverConnectClientThread.getSocket();
                            OutputStream outputStream = socket.getOutputStream();
                            ObjectOutputStream oot = new ObjectOutputStream(outputStream);
                            oot.writeObject(message);//如果用户不在线的话就做成离线的消息了,怎么做呢，就和微信一样，只要自己有网，发了就一定能接收
                        } else {//如果接收者不在线的话把信息保存到集合中，遍历不在线集合id
                            System.out.println("不在线的情况");
                            ConcurrentHashMap<String, Vector<Message>> offLineDB = QQServer.offLineDB;//得到不在线用户集合
                            Iterator<String> iterator = offLineDB.keySet().iterator();
                            while (iterator.hasNext()) {
                                String USerId = iterator.next();//拿到每一个不在线的用户的id，
                                /**
                                 * 就是下面的这个逻辑有问题，导致不能多条发送，创建的Vector多了
                                 */
                                if (message.getGetter().equals(USerId)) {//如果这个id和消息的id相等，则存放这个信息
                                    Vector<Message> messages = offLineDB.get(USerId);
                                    messages.add(message);
                                    System.out.println("用户"+message.getGetter()+"的离线消息消息数量为"+messages.size());
                                }
                                else {//没有的话则在这个集合中加入这个用户的信息，就创建一个Vector对象用于存放消息
                                    Vector<Message> messagess = new Vector<>();
                                    messagess.add(message);
                                    offLineDB.put(message.getGetter(), messagess);
                                    System.out.println("发现用户"+message.getGetter()+"现在不在线创建了唯一信息集合消息数量为"+messagess.size());
                                }
                            }
                        }
                    }


                } else if (message.getMesType().equals(MessageType.MESSAGE_TO_ALL_MES)) {
                    //群发消息遍历每一个在线用户，得到socket，把message进行转发
                    HashMap<String, ServerConnectClientThread> hm = MangerClientThreads.getHm();
                    Iterator<String> iterator = hm.keySet().iterator();
                    System.out.println(message.getSender() + "对大家说:" + message.getContent());
                    while (iterator.hasNext()) {
                        //取出在线用户的id
                        String onLineUserId = iterator.next();
                        //不能给自己发吧，排除群发消息的用户，不能给自己发送消息
                        if (!onLineUserId.equals(message.getSender())) {
                            ObjectOutputStream oos =
                                    new ObjectOutputStream(hm.get(onLineUserId).getSocket().getOutputStream());
                            oos.writeObject(message);
                        }

                    }
                } else if (message.getMesType().equals(MessageType.MESSAGE_FILE_MES)) {
                    //根据message的接受者获得对应的线程
                    ObjectOutputStream oos =
                            new ObjectOutputStream(MangerClientThreads.getServerConnectClientThread(message.getGetter()).socket.getOutputStream());
                    oos.writeObject(message);
                    System.out.println("用户" + message.getSender() + "给" + message.getGetter() + "发送了一个文件");
                } else {
                    System.out.println("暂时不处理");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
